package com.wulian.common.util.excel;

import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


/**
 * excel导出 工具类 poi3.9jar
 * @author : ZN-99999
 * @date : 2019/1/16 12:22
 * @param <T>
 */
public class ExcelExportUtil<T> {

	private static Logger logger = LoggerFactory.getLogger(ExcelExportUtil.class);

	private HttpServletRequest request = null;
	private HttpServletResponse response = null;

	public ExcelExportUtil(HttpServletRequest request, HttpServletResponse response) {
		this.request = request;
		this.response = response;
	}

	/**
	 * 导出
	 * @param fileName
	 * @param excelTempleteName
	 * @param fieldNames
	 * @param dataList
	 * @param startRow
	 * @throws IOException
	 */
	public void exportExcel(String fileName, String excelTempleteName, String fieldNames,
							List<T> dataList, int startRow) throws IOException {
		//构建输出流
		OutputStream os = null;
		Workbook wb = null;
		InputStream inputStream = null;
		String exportType = fileName;
		try {
			inputStream = this.getClass().getResourceAsStream("/excel/" + excelTempleteName);//文件存放路径
			String userAgent = request.getHeader("user-Agent");
			//针对IE或者以IE为内核的浏览器：
			if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
				fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
			} else {
				//非IE浏览器的处理：
				//fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
			}
			//获得文件模板
			wb = getWorkbookByParams(inputStream, dataList, fieldNames, startRow);
			response.setContentType("application/vnd.ms-excel;charset=utf-8;fileName="+fileName);
			//response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
			response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName+".xlsx", "UTF-8"));
			os = response.getOutputStream();
			wb.write(os);
		} catch (Exception e) {
			logger.error(exportType + " 导出操作异常,原因:", e);
		} finally {
			logger.info("开始关流");
			if(null != os){
				os.flush();
				os.close();
			}

		}
	}

	/**
	 * 描述：设置简单的Cell样式
	 * @return
	 */
	public  CellStyle setSimpleCellStyle(Workbook wb){
		CellStyle cs = wb.createCellStyle();
		/*//下边框
		cs.setBorderBottom(CellStyle.BORDER_THIN);
		//左边框
		cs.setBorderLeft(CellStyle.BORDER_THIN);
		//上边框
		cs.setBorderTop(CellStyle.BORDER_THIN);
		//右边框
		cs.setBorderRight(CellStyle.BORDER_THIN);
		// 居中
		cs.setAlignment(CellStyle.ALIGN_CENTER);*/
		//下边框
		cs.setBorderBottom(BorderStyle.THIN);
		//左边框
		cs.setBorderLeft(BorderStyle.THIN);
		//上边框
		cs.setBorderTop(BorderStyle.THIN);
		//右边框
		cs.setBorderRight(BorderStyle.THIN);
		// 左右居中
		cs.setAlignment(HorizontalAlignment.CENTER);
		//垂直居中
		cs.setVerticalAlignment(VerticalAlignment.CENTER); //直居中（上下居中）
		return cs;
	}

	public Workbook getWorkbookByParams(InputStream inputStream, List<?> list, String fieldName, int startRow) throws Exception {
		Workbook wb = null;
		Cell cell = null;
		int rowNum = 1;
		String[] fieldNameArr = fieldName.split(",");
		if (!inputStream.markSupported()) {
			inputStream = new PushbackInputStream(inputStream, 8);
		}
		wb = WorkbookFactory.create(inputStream);//
		/*if (POIFSFileSystem.hasPOIFSHeader(inputStream)) {
			wb= new HSSFWorkbook(inputStream);
		}else if (POIXMLDocument.hasOOXMLHeader(inputStream)) {
//			wb = new XSSFWorkbook(OPCPackage.open(inputStream));
			wb = new SXSSFWorkbook((XSSFWorkbook) new XSSFWorkbook(OPCPackage.open(inputStream)));
		}*/
		//取得指定的SHEET页
		Sheet sheet = wb.getSheetAt(0);
		//Excel单元格样式
		CellStyle cs = setSimpleCellStyle(wb);
		//处理sheet第一页数据
		for (Object obj : list) {
			Row row = sheet.getRow(startRow);
			if(null == row){
				row = sheet.createRow(startRow);
			}
			for (int i = 0; i < fieldNameArr.length; i++) {
				cell = row.createCell(i);
				if(fieldNameArr[i].equals("row_num_flag")){//导出列表有:序号  需求标示
					cell.setCellValue(rowNum++);
				}else{
					cell.setCellValue(invokeMethod(obj,fieldNameArr[i]));
				}
				cell.setCellStyle(cs);
			}
			startRow++;
		}
		wb.setForceFormulaRecalculation(true);
		return wb;
	}

	/**
	 * 通过反射 动态获取属性值
	 *
	 * @param obj
	 * @param fieldname
	 * @return
	 * @throws Exception
	 */
	private String invokeMethod(Object obj, String fieldname) throws Exception {
		String resultValue = "";
		PropertyDescriptor pd = null;
		try {
			pd = new PropertyDescriptor(fieldname, obj.getClass());
		}catch (Exception e){
			logger.error("列表实体类中没有属性: "+fieldname+ ",请检查参数:fieldNames 填写是否正确!");
			//throw new BusinessException("列表实体类中没有属性: "+fieldname+",请检查参数:fieldNames 填写是否正确!");
			return resultValue;
		}
		//获取get方法
		Method methodGetX = pd.getReadMethod();
		Object reValue = methodGetX.invoke(obj);
		if (null != reValue) {
			if (reValue instanceof Date) {
				resultValue = dateToString((Date) reValue, "yyyy-MM-dd");
			} else {
				resultValue = reValue.toString();
				resultValue = resultValue.replace("null","");
			}
		}
		return resultValue;
	}

	public static String dateToString(Date paramDate, String pattern)
	{
		return doDateFormat(pattern).format(paramDate);
	}
	public static DateFormat doDateFormat(String pattern)
	{
		return new SimpleDateFormat(pattern);
	}
}
